/**
*    Copyright (C) 2008  Chase Kernan 
*    chase.kernan@gmail.com
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
**/

package com.chasekernan.hxnova.client.mapviewer;

import com.chasekernan.hxnova.core.fleets.Fleet;
import com.chasekernan.hxnova.utils.Vector;
import com.chasekernan.hxnova.core.SpaceObject;
import com.chasekernan.hxnova.core.players.Player;
import com.chasekernan.hxnova.core.players.PlayerRelations;
import com.chasekernan.hxnova.utils.Utils;

import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

class FleetObject extends Sprite, implements IMapObject {
    
    public static var FLEET_WAYPOINT_LINE_COLOR = 0x0099CC;
    public static var FLEET_TEXT_COLOR = 0xFF0000;
    public static var FLEET_TEXT_SIZE = 10;
    public static var FLEET_WAYPOINT_LINE_SIZE = 1;
    public static var WARP_MARKER_LENGTH = 3;
    public static var WARP_MARKER_ANGLE = Math.PI / 4;
    public static var TRIANGLE_LENGTH = 7;
    public static var TRIANGLE_ANGLE = Math.PI / 4;
    
    /**
        How many warps to extend the direction line for a foriegn fleet.
    **/
    public static var NUM_WARPS = 5;
    
    public var fleet : Fleet;
    
    private var nameBox : TextField;
    private var amountBox : TextField;
    
    public function new(fleet : Fleet) {
        super();
        
        this.fleet = fleet;
        
        nameBox = Utils.createGenericTextBox(fleet.name, FLEET_TEXT_COLOR, 
                                             FLEET_TEXT_SIZE);
        addChild(nameBox);
        
        var amount = 0;
        for (stack in fleet.ships) amount += stack.amount;
        amountBox = Utils.createGenericTextBox(Std.string(amount), 
                                               FLEET_TEXT_COLOR, 
                                               FLEET_TEXT_SIZE);
        addChild(amountBox);
    }
    
    public function getObject() : SpaceObject {
        return fleet;
    }
    
    public function draw(bounds : Rectangle, player : Player, 
                         options : MapOptions) {
        if (!options.drawFleets) return;
        
        handleTriangle(bounds, player);
        if (fleet.waypoints != null) handleWaypoints(bounds, player);
        handleFleetName(bounds, options);
        handleFleetAmount(bounds, options);
    }
    
    private function handleFleetName(bounds, options : MapOptions) {
        if (fleet.name == null || fleet.name == "") return;
        
        if (!options.drawFleetAmounts) {
            nameBox.visible = false;
            return;
        }
        nameBox.visible = true;
        
        var recip = 1.0 / options.zoom;
        
        nameBox.x = fleet.location.x - Std.int(bounds.x) - 50 * recip;
        nameBox.y = fleet.location.y - Std.int(bounds.y) + 5 * recip;
        //nameBox.scaleX = recip;
        //nameBox.scaleY = recip;
    }
    
    private function handleFleetAmount(bounds, options : MapOptions) {
        if (fleet.ships == null || fleet.ships.length == 0) return;
        
        if (!options.drawFleetAmounts) {
            amountBox.visible = false;
            return;
        }
        amountBox.visible = true;
            
        var recip = 1.0 / options.zoom;
        
        amountBox.x = fleet.location.x - Std.int(bounds.x) - 50 * recip;
        amountBox.y = fleet.location.y - Std.int(bounds.y) - 15 * recip;
        amountBox.scaleX = recip;
        amountBox.scaleY = recip;
    }
    
    private function handleWaypoints(bounds : Rectangle, player : Player) {
        var start = fleet.location.clone();
        
        for (waypoint in fleet.waypoints) {
            var target = switch(waypoint.target) {
                
                case Location(v): v;
                
                case StarTarget(s):
                    if (s == null) null else s.location;
                    
                case FleetTarget(f):
                    if (f == null || f.location == null) null 
                    else f.location;
                    
            };
            if (target == null) break;
            
            drawWaypointLine(bounds, start, target, waypoint.warp);
        }
    }
    
    private function handleTriangle(bounds : Rectangle, player : Player) {
        var color = 
        if (fleet.owner == null || fleet.owner.id == -1) MapViewer.NUETRAL_COLOR
        else if (player.id == fleet.owner.id) MapViewer.SELF_COLOR
        else {
            switch(player.relations.getRelationTo(fleet.owner)) {
                
                case Enemy: MapViewer.ENEMY_COLOR;
                case Nuetral: MapViewer.NUETRAL_COLOR;
                case Friend: MapViewer.FRIENDLY_COLOR;
                
            }
        };
        
        graphics.lineStyle(0, 0, 0.0);
        graphics.beginFill(color, 1.0);
        
        var loc = new Vector(fleet.location.x - bounds.x, 
                             fleet.location.y - bounds.y);
        graphics.moveTo(loc.x, loc.y);
        
        var angle = 
        if (fleet.waypoints == null)
            if (fleet.bearing == null) 0.0 else fleet.bearing
        else if (fleet.isStopped()) 0.0 else fleet.getBearing();
        
        var left = loc.getAdd(
                Vector.fromAngle(angle + Math.PI / 2 + TRIANGLE_ANGLE,
                                 TRIANGLE_LENGTH));
        var right = loc.getAdd(
                Vector.fromAngle(angle - Math.PI / 2 - TRIANGLE_ANGLE,
                                 TRIANGLE_LENGTH));
        
        graphics.lineTo(left.x, left.y);
        graphics.lineTo(right.x, right.y);
        graphics.lineTo(loc.x, loc.y);
        graphics.endFill();
    }
    
    
    public function drawProjections(bounds : Rectangle, player : Player, 
                                    options : MapOptions) {
        if (fleet.waypoints != null || fleet.bearing == null || 
                fleet.scannedWarp == null) return;
        
        var vec = Vector.fromAngle(fleet.bearing, 
                                    fleet.scannedWarp * fleet.scannedWarp * 
                                            NUM_WARPS);
        drawWaypointLine(bounds, fleet.location, fleet.location.getAdd(vec),
                         fleet.scannedWarp);
        drawWaypointLine(bounds, fleet.location.getSub(vec), fleet.location,
                         fleet.scannedWarp);
        
        //put the fleet triangle on top again
        handleTriangle(bounds, player);
    }
    
    private function drawWaypointLine(bounds : Rectangle, start : Vector, 
                                      end : Vector, warp : Int) {
        graphics.lineStyle(FLEET_WAYPOINT_LINE_SIZE, 
                           FLEET_WAYPOINT_LINE_COLOR);
        var e = new Vector(end.x - bounds.x, end.y - bounds.y);
        var s = new Vector(start.x - bounds.x, start.y - bounds.y);
        
        graphics.moveTo(s.x, s.y);
        graphics.lineTo(e.x, e.y);
        
        var dist = s.distanceTo(e);
        var numMarks = Math.ceil(dist / (warp * warp));
        var diff = e.getSub(s);
        var angle = diff.getAngle();
        
        for (i in 1...numMarks) {
            var point = start.getAdd(diff.getScale(i * warp * warp / dist));
            var left = point.getAdd(
                    Vector.fromAngle(angle + Math.PI / 2 + WARP_MARKER_ANGLE,
                                     WARP_MARKER_LENGTH));
            var right = point.getAdd(
                    Vector.fromAngle(angle - Math.PI / 2 - WARP_MARKER_ANGLE, 
                                     WARP_MARKER_LENGTH));
            
            graphics.moveTo(point.x, point.y);
            graphics.lineTo(left.x, left.y);
            graphics.moveTo(point.x, point.y);
            graphics.lineTo(right.x, right.y);
        }
    }
}